package com.zzyl.nursing.service.impl;


import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.BindFamilyMemberDTO;
import com.zzyl.nursing.dto.HealthDataDayDto;
import com.zzyl.nursing.dto.HealthDataDto;
import com.zzyl.nursing.mapper.DeviceDataMapper;
import com.zzyl.nursing.mapper.DeviceMapper;
import com.zzyl.nursing.mapper.ElderMapper;
import com.zzyl.nursing.mapper.FamilyMemberElderMapper;
import com.zzyl.nursing.service.IFamilyMemberElderService;
import com.zzyl.nursing.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static java.time.Instant.ofEpochMilli;
import static java.time.ZoneId.systemDefault;

/**
 * 家属-老人多对多中间Service业务层处理
 * 
 * @author alexis
 * @date 2025-10-26
 */
@Service
public class FamilyMemberElderServiceImpl extends ServiceImpl<FamilyMemberElderMapper, FamilyMemberElder> implements IFamilyMemberElderService
{
    @Autowired
    private FamilyMemberElderMapper familyMemberElderMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private DeviceDataMapper deviceDataMapper;

    /**
     * 绑定家人
     * @param bindFamilyMemberDTO
     */
    @Override
    public void postFamilyMember(BindFamilyMemberDTO bindFamilyMemberDTO) {
        Long idCard = elderMapper.findIdCardId(bindFamilyMemberDTO.getIdCard());
        //身份证信息有误或姓名有误
        String idCardName = elderMapper.findIdCardName(bindFamilyMemberDTO.getIdCard());
        if(idCard == null||!bindFamilyMemberDTO.getName().equals(idCardName)){
            throw new BaseException("老人身份证信息有误，检查身份证信息");
        };
        Long userId = Long.valueOf(UserThreadLocal.getUserId());//获取当前微信登录人id
        FamilyMemberElder familyMemberElder = new FamilyMemberElder(null,idCard,userId);
        familyMemberElder.setRemark(bindFamilyMemberDTO.getRemark());
        familyMemberElder.setCreateBy(String.valueOf(UserThreadLocal.getUserId()));
        //表中有重复数据,存储失败
        this.list().forEach(l ->
                {
                    if (l.getElderId().equals(familyMemberElder.getElderId())&&l.getFamilyMemberId().equals(familyMemberElder.getFamilyMemberId())) {
                        throw new BaseException("老人信息已绑定");
                    }
                }
                );
        this.save(familyMemberElder);
    }

    /**
     * 查询家人列表
     * @return
     */
    @Override
    public List<FamilyMemberListVO> getFamilyListByUserId() {
        String s = String.valueOf(UserThreadLocal.getUserId());
        System.out.println(familyMemberElderMapper.findid(s).toString());
        return familyMemberElderMapper.findid(s);
    }

    /**
     * 查看家人列表（分页查询）
     * @param pageQuery
     * @return
     */
    @Override
    public List<FamilyMemberElderpageVo> getFamilyMemberListByPage(PageQuery pageQuery) {
        PageHelper.startPage(pageQuery.getPageNum(), pageQuery.getPageSize());
        List<FamilyMemberElderpageVo> listpage = familyMemberElderMapper.listpage(String.valueOf(UserThreadLocal.getUserId()));
        //绑定设备信息
        for(FamilyMemberElderpageVo familyMemberElder :listpage ){
        FamilyMemberElderpageVo data = deviceMapper.findiddevice(familyMemberElder.getName());
            if (data != null) {
                familyMemberElder.setIotId(data.getIotId());
                familyMemberElder.setDeviceName(data.getDeviceName());
                familyMemberElder.setProductKey(data.getProductKey());
            } else {
                // 可选：设置默认值或留空
                familyMemberElder.setIotId(null);
                familyMemberElder.setDeviceName(null);
                familyMemberElder.setProductKey(null);
            }
        };
        return listpage;
    }

    /**
     * 健康数据查询
     * @param healthDataDto
     * @return
     */
    @Override
    public HealthDataVO healthData(HealthDataDto healthDataDto) {
        HealthDataVO healthDataVO = new HealthDataVO();
        List<Object> values = redisTemplate.opsForHash().values(CacheConstants.IOT_DEVICE_DATA_LATEST);
        List<DeviceData> deviceDataListAll = new ArrayList<>();
        for (Object value : values) {
            String deviceDataListJSON = (String) value;
            List<DeviceData> deviceDataList = JSONUtil.toList(deviceDataListJSON, DeviceData.class);
            deviceDataListAll.addAll(deviceDataList);
        }
        List<PropertyStatusInfo> propertyStatusInfoList = new ArrayList<>();
        for (DeviceData deviceData:deviceDataListAll){
            //判断数据是否是该设备
            if (healthDataDto.getDeviceName().equals(deviceData.getDeviceName())&&healthDataDto.getProductKey().equals(deviceData.getProductKey())){
                String functionId = deviceData.getFunctionId();
                String timestamp = String.valueOf(deviceData.getAlarmTime().atZone(systemDefault()).toInstant().toEpochMilli());
                String dataValue = deviceData.getDataValue();
                propertyStatusInfoList.add(new PropertyStatusInfo(functionId,timestamp,dataValue));
            };
        }
        List<PropertyStatusInfo> propertyStatusInfoList1 = ensureHeartRateAtFourthPosition(propertyStatusInfoList);
        ListInfo listInfo = new ListInfo();
        listInfo.setPropertyStatusInfo(propertyStatusInfoList1);
        healthDataVO.setList(listInfo);
        return healthDataVO;

    }
    //工具类：调整顺序，将心跳的数据始终为第四个
    public static List<PropertyStatusInfo> ensureHeartRateAtFourthPosition(List<PropertyStatusInfo> dataList) {
        if (dataList == null) {
            return null;
        }

        // 如果列表长度不足 4，无法保证第四个位置，可根据业务决定是否填充或报错
        // 此处选择：若长度不足 4，则直接返回（或可抛异常）
        if (dataList.size() < 4) {
            return dataList;
        }

        // 查找 HeartRate 对象及其索引
        PropertyStatusInfo heartRateInfo = null;
        int heartRateIndex = -1;

        for (int i = 0; i < dataList.size(); i++) {
            PropertyStatusInfo info = dataList.get(i);
            if ("HeartRate".equals(info.getIdentifier())) {
                heartRateInfo = info;
                heartRateIndex = i;
                break; // 只处理第一个 HeartRate
            }
        }

        // 如果没找到 HeartRate，直接返回
        if (heartRateInfo == null) {
            return dataList; // 或 throw new IllegalArgumentException("HeartRate not found in the list");
        }

        // 如果已经在第四个位置（索引 3），无需操作
        if (heartRateIndex == 3) {
            return dataList;
        }

        // 从原位置移除
        dataList.remove(heartRateIndex);

        // 插入到索引 3（第四个位置）
        dataList.add(3, heartRateInfo);

        return dataList;
    }


    
    @Override
    public List<HealthVo> healthDayData(HealthDataDayDto healthDataDayDto) {
        String iotId = healthDataDayDto.getIotId();
        LambdaQueryWrapper<DeviceData> queryWrapper = new LambdaQueryWrapper<>();
        LocalDateTime startTime = LocalDateTime.ofInstant(
                ofEpochMilli(healthDataDayDto.getStartTime()),
                systemDefault());
        LocalDateTime endTime = LocalDateTime.ofInstant(
                        ofEpochMilli(healthDataDayDto.getEndTime()),
                        systemDefault())
                .withNano(0);  // 去掉毫秒部分
        queryWrapper.eq(DeviceData::getIotId, iotId).
                eq(DeviceData::getFunctionId, healthDataDayDto.getFunctionId()).
                ge(DeviceData::getAlarmTime, startTime).
                le(DeviceData::getAlarmTime, endTime); // 找寻时间范围
        List<DeviceData> deviceData = deviceDataMapper.selectList(queryWrapper);

        // 按小时分组统计数据
        Map<Integer, List<Double>> hourlyDataMap = new LinkedHashMap<>();

        // 初始化24小时的数据（0-23小时）
        for (int i = 0; i < 24; i++) {
            hourlyDataMap.put(i, new ArrayList<>());
        }

        // 将查询到的数据按小时分组
        for (DeviceData deviceDatum : deviceData) {
            LocalDateTime alarmTime = deviceDatum.getAlarmTime();
            int hour = alarmTime.getHour();

            try {
                double value = Double.parseDouble(deviceDatum.getDataValue());
                hourlyDataMap.get(hour).add(value);
            } catch (NumberFormatException e) {
                // 忽略无法解析为数字的数据
            }
        }

        // 计算每小时的平均值并构建返回结果
        List<HealthVo> result = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");

        for (int hour = 0; hour < 24; hour++) {
            HealthVo vo = new HealthVo();
            List<Double> values = hourlyDataMap.get(hour);

            // 计算平均值
            double averageValue = 0.0;
            if (!values.isEmpty()) {
                double sum = 0.0;
                for (Double value : values) {
                    sum += value;
                }
                averageValue = sum / values.size();
            }

            vo.setDataValue(averageValue);
            // 格式化小时时间，例如 "00:00", "01:00" 等
            LocalDateTime hourTime = startTime.toLocalDate().atTime(hour, 0);
            vo.setDateTime(hourTime.format(formatter));
            result.add(vo);
        }

        return result;
    }



    @Override
    public List<HealthWeekVo> healthWeekData(HealthDataDayDto healthDataDayDto) {
        String iotId = healthDataDayDto.getIotId();
        LambdaQueryWrapper<DeviceData> queryWrapper = new LambdaQueryWrapper<>();
        LocalDateTime startTime = LocalDateTime.ofInstant(
             ofEpochMilli(healthDataDayDto.getStartTime()),
             systemDefault());

        LocalDateTime endTime = LocalDateTime.ofInstant(
                        ofEpochMilli(healthDataDayDto.getEndTime()),
                        systemDefault())
                .withNano(0);  // 去掉毫秒部分
        queryWrapper.eq(DeviceData::getIotId, iotId).
                eq(DeviceData::getFunctionId, healthDataDayDto.getFunctionId()).
                ge(DeviceData::getAlarmTime, startTime).
                le(DeviceData::getAlarmTime, endTime);// 找寻时间范围

        List<DeviceData> deviceData = deviceDataMapper.selectList(queryWrapper);

        // 按天分组统计数据
        Map<LocalDateTime, List<Integer>> dailyDataMap = new LinkedHashMap<>();

        // 初始化一周七天的数据
        LocalDateTime currentDate = startTime.toLocalDate().atStartOfDay();
        while (!currentDate.isAfter(endTime)) {
            dailyDataMap.put(currentDate, new ArrayList<>());
            currentDate = currentDate.plusDays(1);
        }

        // 将查询到的数据按日期分组
        for (DeviceData deviceDatum : deviceData) {
            LocalDateTime alarmTime = deviceDatum.getAlarmTime();
            LocalDateTime dateKey = alarmTime.toLocalDate().atStartOfDay();

            if (dailyDataMap.containsKey(dateKey)) {
                try {
                    double value = Double.parseDouble(deviceDatum.getDataValue());
                    int intValue = (int) Math.round(value); // 四舍五入转换为整数
                    dailyDataMap.get(dateKey).add(intValue);
                } catch (NumberFormatException e) {
                    // 忽略无法解析为数字的数据
                }
            }
        }

        // 计算每天的平均值并构建返回结果
        List<HealthWeekVo> result = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM.dd");

        for (Map.Entry<LocalDateTime, List<Integer>> entry : dailyDataMap.entrySet()) {
            HealthWeekVo vo = new HealthWeekVo();
            LocalDateTime dateKey = entry.getKey();
            List<Integer> values = entry.getValue();

            // 计算平均值（整数类型）
            int averageValue = 0;
            if (!values.isEmpty()) {
                int sum = 0;
                for (Integer value : values) {
                    sum += value;
                }
                // 四舍五入计算平均值
                averageValue = (int) Math.round((double) sum / values.size());
            }
            vo.setDataValue(averageValue);
            // 使用 MM.dd 格式，例如 "01.15"
            vo.setDateTime(dateKey.format(formatter));
            result.add(vo);
        }

        return result;
    }
}
